package com.team.databoard.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.team.databoard.common.ErrorCode;
import com.team.databoard.constant.StudentConstant.*;
import com.team.databoard.exception.BusinessException;
import com.team.databoard.model.Student;
import com.team.databoard.service.StudentService;
import com.team.databoard.mapper.StudentMapper;
import com.team.databoard.util.DatabaseUtils;
import com.team.databoard.util.EnumUtils;
import com.team.databoard.util.VerifyUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author XiaoZheng2003
 * @description 针对表【student】的数据库操作Service实现
 * @createDate 2024-08-23 19:40:34
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student>
        implements StudentService {

    @Resource
    private StudentMapper studentMapper;

    // ---------------基本操作----------------

    /**
     * 新增学生
     *
     * @param student 学生实体
     * @return 学生id
     */
    @Override
    public int insertStudent(Student student) {
        // 验证学生信息是否合法
        if (!VerifyUtils.isStudentValid(student)) {
            return -1;
        }
        try {
            this.save(student);
            return student.getId();
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 删除学生
     *
     * @param id 学生id
     * @return 是否删除成功
     */
    @Override
    public boolean deleteStudent(int id) {
        return this.removeById(id);
    }

    /**
     * 更新学生
     *
     * @param student 学生实体
     * @return 是否更新成功
     */
    @Override
    public boolean updateStudent(Student student) {
        // 验证学生信息是否合法
        if (!VerifyUtils.isStudentValidFilled(student)) {
            return false;
        }
        return this.updateById(student);
    }

    /**
     * 查询学生
     *
     * @param id 学生id
     * @return 学生实体
     */
    @Override
    public Student selectStudent(int id) {
        return this.getById(id);
    }

    /**
     * 查询学生列表
     *
     * @param params 查询条件
     * @param page   页码
     * @param size   每页数量
     * @return 学生列表及数据条数
     */
    @Override
    public Map<String, Object> selectStudent(int page, int size, Map<String, Object> params) {
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();

        params.forEach((key, value) -> {
            switch (key) {
                case "id":
                    handleRangeQuery(queryWrapper, "id", value.toString());
                    break;
                case "name":
                    queryWrapper.like("name", value);
                    break;
                case "sex":
                    queryWrapper.eq("sex", value);
                    break;
                case "province":
                    queryWrapper.eq("province", value);
                    break;
                case "birthday":
                    handleRangeQuery(queryWrapper, "birthday", value.toString());
                    break;
                case "height":
                    handleRangeQuery(queryWrapper, "height", value.toString());
                    break;
                case "education":
                    queryWrapper.eq("education", value);
                    break;
                case "age":
                    handleAgeQuery(queryWrapper, value.toString());
                    break;
                default:
                    break;
            }
        });

        Page<Student> studentPage = new Page<>(page, size);
        IPage<Student> iPage = studentMapper.selectPage(studentPage, queryWrapper);
        return Map.of("list", iPage.getRecords(), "total", iPage.getTotal());
    }

    /**
     * 处理范围查询
     *
     * @param queryWrapper 查询条件
     * @param field        字段
     * @param value        值
     */
    private void handleRangeQuery(QueryWrapper<Student> queryWrapper, String field, String value) {
        boolean rangeQuery = value.contains(",");
        String[] bounds = value.split(",");
        if (rangeQuery) {
            if (!bounds[0].isEmpty()) {
                queryWrapper.ge(field, bounds[0]);
            }
            if (bounds.length > 1 && !bounds[1].isEmpty()) {
                queryWrapper.le(field, bounds[1]);
            }
        } else {
            queryWrapper.eq(field, bounds[0]);
        }
    }

    /**
     * 处理年龄查询
     *
     * @param queryWrapper 查询条件
     * @param value        值
     */
    private void handleAgeQuery(QueryWrapper<Student> queryWrapper, String value) {
        boolean rangeQuery = value.contains(",");
        String[] bounds = value.split(",");
        LocalDate now = LocalDate.now();
        if (rangeQuery) {
            if (!bounds[0].isEmpty()) {
                LocalDate endDate = now.minusYears(Long.parseLong(bounds[0]));
                queryWrapper.le("birthday", endDate);
            }
            if (bounds.length > 1 && !bounds[1].isEmpty()) {
                LocalDate startDate = now.minusYears(Long.parseLong(bounds[1]) + 1);
                queryWrapper.gt("birthday", startDate);
            }
        } else {
            LocalDate startDate = now.minusYears(Long.parseLong(bounds[0]) + 1).plusDays(1);
            LocalDate endDate = now.minusYears(Long.parseLong(bounds[0]));
            queryWrapper.between("birthday", startDate, endDate);
        }
    }

    // ---------------统计操作----------------

    /**
     * 姓氏统计
     *
     * @param provinceId 省份id
     * @return 姓氏统计
     */
    @Override
    public List<Map<String, Object>> groupByLastName(Integer provinceId) {
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        if (provinceId != null) {
            if (EnumUtils.isIncludeCode(Province.class, provinceId)) {
                queryWrapper.eq("province", provinceId);
            } else {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
        }
        queryWrapper.select("left(name,1) as lastname, count(*) as count").groupBy("lastname");
        return studentMapper.selectMaps(queryWrapper);
    }

    /**
     * 性别统计
     *
     * @param provinceId 省份id
     * @return 性别统计
     */
    @Override
    public Map<String, Integer> groupBySex(Integer provinceId) {
        return DatabaseUtils.groupBy(studentMapper, "sex", provinceId, List.of("0", "1"));
    }

    /**
     * 省份统计
     *
     * @param provinceId 省份id
     * @return 省份统计
     */
    @Override
    public Map<String, Integer> groupByProvince(Integer provinceId) {
        return DatabaseUtils.groupBy(studentMapper, "province", provinceId);
    }

    /**
     * 生日月份统计
     *
     * @param provinceId 省份id
     * @return 生日月份统计
     */
    @Override
    public Map<String, Integer> groupByBirthMonth(Integer provinceId) {
        return DatabaseUtils.groupBy(studentMapper, "month(birthday)", provinceId);
    }

    /**
     * 生日年份统计
     *
     * @param provinceId 省份id
     * @return 生日年份统计
     */
    @Override
    public Map<String, Integer> groupByBirthYear(Integer provinceId) {
        return DatabaseUtils.groupBy(studentMapper, "year(birthday)", provinceId);
    }

    /**
     * 身高统计
     *
     * @param provinceId 省份id
     * @return 身高统计
     */
    @Override
    public Map<String, Integer> groupByHeight(Integer provinceId) {
        return DatabaseUtils.groupBy(studentMapper, "height", provinceId);
    }

    /**
     * 学历统计
     *
     * @param provinceId 省份id
     * @return 学历统计
     */
    @Override
    public Map<String, Integer> groupByEducation(Integer provinceId) {
        return DatabaseUtils.groupBy(studentMapper, "education", provinceId, List.of("0", "1", "2"));
    }

    /**
     * 获得学生总人数
     *
     * @return 学生总人数
     */
    @Override
    public int getStudentCount() {
        return studentMapper.selectCount(null).intValue();
    }

    /**
     * 获取实时更新学生列表
     *
     * @return 实时更新学生列表
     */
    @Override
    public Map<String, Object> getUpdateList(int count) {
        // 此处采用随机获取若干条数据的方法进行模拟
        List<Integer> studentIds = studentMapper.selectList(new QueryWrapper<Student>().select("id"))
                .stream()
                .map(Student::getId)
                .collect(Collectors.toList());
        if (studentIds.isEmpty()) {
            return Map.of("list", List.of(), "total", 0);
        }
        Collections.shuffle(studentIds);
        List<Integer> selectedIds = studentIds.stream().limit(count).collect(Collectors.toList());
        List<Student> result = studentMapper.selectBatchIds(selectedIds);
        return Map.of("list", result, "total", result.size());
    }
}
